home *** CD-ROM | disk | FTP | other *** search
- //: C25:VirtualConstructor.cpp
- // From Thinking in C++, 2nd Edition
- // Available at http://www.BruceEckel.com
- // (c) Bruce Eckel 1999
- // Copyright notice in Copyright.txt
- #include <iostream>
- #include <string>
- #include <exception>
- #include <vector>
- using namespace std;
-
- class Shape {
- Shape* s;
- // Prevent copy-construction & operator=
- Shape(Shape&);
- Shape operator=(Shape&);
- protected:
- Shape() { s = 0; };
- public:
- virtual void draw() { s->draw(); }
- virtual void erase() { s->erase(); }
- virtual void test() { s->test(); };
- virtual ~Shape() {
- cout << "~Shape\n";
- if(s) {
- cout << "Making virtual call: ";
- s->erase(); // Virtual call
- }
- cout << "delete s: ";
- delete s; // The polymorphic deletion
- }
- class BadShapeCreation : public exception {
- string reason;
- public:
- BadShapeCreation(string type) {
- reason = "Cannot create type " + type;
- }
- const char *what() const {
- return reason.c_str();
- }
- };
- Shape(string type) throw(BadShapeCreation);
- };
-
- class Circle : public Shape {
- Circle(Circle&);
- Circle operator=(Circle&);
- Circle() {} // Private constructor
- friend class Shape;
- public:
- void draw() { cout << "Circle::draw\n"; }
- void erase() { cout << "Circle::erase\n"; }
- void test() { draw(); }
- ~Circle() { cout << "Circle::~Circle\n"; }
- };
-
- class Square : public Shape {
- Square(Square&);
- Square operator=(Square&);
- Square() {}
- friend class Shape;
- public:
- void draw() { cout << "Square::draw\n"; }
- void erase() { cout << "Square::erase\n"; }
- void test() { draw(); }
- ~Square() { cout << "Square::~Square\n"; }
- };
-
- Shape::Shape(string type)
- throw(Shape::BadShapeCreation) {
- if(type == "Circle")
- s = new Circle();
- else if(type == "Square")
- s = new Square();
- else throw BadShapeCreation(type);
- draw(); // Virtual call in the constructor
- }
-
- char* shlist[] = { "Circle", "Square", "Square",
- "Circle", "Circle", "Circle", "Square", "" };
-
- int main() {
- vector<Shape*> shapes;
- cout << "virtual constructor calls:" << endl;
- try {
- for(char** cp = shlist; **cp; cp++)
- shapes.push_back(new Shape(*cp));
- } catch(Shape::BadShapeCreation e) {
- cout << e.what() << endl;
- return 1;
- }
- for(int i = 0; i < shapes.size(); i++) {
- shapes[i]->draw();
- cout << "test\n";
- shapes[i]->test();
- cout << "end test\n";
- shapes[i]->erase();
- }
- Shape c("Circle"); // Create on the stack
- cout << "destructor calls:" << endl;
- for(int j = 0; j < shapes.size(); j++) {
- delete shapes[j];
- cout << "\n------------\n";
- }
- } ///:~
-